﻿#include <iostream>
#include <algorithm>
#include <string.h>
#include "bytearraystream.h"

BytearrayInputStream::BytearrayInputStream() :BytearrayInputStream(std::make_shared<ByteArrayBuffer>())
{
}

BytearrayInputStream::BytearrayInputStream(const unsigned char * buffer, int bufferLen):BytearrayInputStream(std::make_shared<ByteArrayBuffer>(buffer,bufferLen))
{
	
}

BytearrayInputStream::BytearrayInputStream(ByteArrayBufferPtr buffer)
{
	this->buffer = buffer;
}

int BytearrayInputStream::doRead(unsigned char * buffer, int readLen) throw(StreamException)
{
	return this->buffer->Read(buffer, readLen);
}

int BytearrayInputStream::avaliable() const
{
	return this->buffer->Avaliable();
}

ByteArrayBufferPtr BytearrayInputStream::GetBuffer()
{
	return buffer;
}

ByteArray BytearrayOutputStream::GetByteArray() const
{
	return buffer->GetContent();
}

void BytearrayInputStream::close()
{
	buffer->Close();
}

BytearrayOutputStream::BytearrayOutputStream() :BytearrayOutputStream(std::make_shared<ByteArrayBuffer>())
{
}

BytearrayOutputStream::BytearrayOutputStream(ByteArrayBufferPtr buffer)
{
	this->buffer = buffer;
}

void BytearrayOutputStream::close()
{
	buffer->Close();
}

ByteArrayBufferPtr BytearrayOutputStream::GetBuffer()
{
	return buffer;
}

void BytearrayOutputStream::write(const unsigned char * buffer, int len) throw(StreamException)
{
	this->buffer->Write(buffer, len);
}

ByteArrayBuffer::ByteArrayBuffer()
{
	isClosed = false;
	isFinished = false;
}

ByteArrayBuffer::~ByteArrayBuffer()
{
	Close();
}

ByteArrayBuffer::ByteArrayBuffer(const unsigned char * buffer, int bufferLen):ByteArrayBuffer()
{
	this->buffer = {buffer,bufferLen + buffer};
}

int ByteArrayBuffer::Avaliable() const
{
	std::lock_guard<std::mutex> lock(m_mutex);
	return buffer.size();
}

void ByteArrayBuffer::Close()
{
	std::lock_guard<std::mutex> lock(m_mutex);
	if (!isClosed) {
		isClosed = true;
		buffer.clear();
		m_con.notify_all();
	}
}

void ByteArrayBuffer::Finish()
{
	std::lock_guard<std::mutex> lock(m_mutex);
	if (!isFinished) {
		isFinished = true;
		m_con.notify_all();
	}
}

ByteArray ByteArrayBuffer::GetContent() const
{
	// TODO: 在此处插入 return 语句
	std::lock_guard<std::mutex> lock(m_mutex);
	return buffer;
}

void ByteArrayBuffer::Reset()
{
	std::lock_guard<std::mutex> lock(m_mutex);
	buffer.clear();
	isClosed = false;
	isFinished = false;
	m_con.notify_all();
}

int ByteArrayBuffer::Read(unsigned char * buffer, int readLen) throw(StreamException)
{
	std::unique_lock<std::mutex> lock(m_mutex);

	if (isClosed) {
		throw StreamException("ByteArrayBuffer Error:Buffer Closed,Read Failed!");
	}

	while (true)
	{
		if (isClosed) {
			throw StreamException("ByteArrayBuffer Error:Buffer Closed,Read Failed!");
		}

		if (isFinished) {
			readLen = this->buffer.size();
			break;
		}

		if (this->buffer.size() >= readLen) {
			break;
		}
		m_con.wait(lock);
	}



	memcpy(buffer, this->buffer.data(), readLen);
	this->buffer.erase(this->buffer.begin(), this->buffer.begin() + readLen);

	return readLen;
}

bool ByteArrayBuffer::Write(const unsigned char * buffer, int len) throw(StreamException)
{
	std::lock_guard<std::mutex> lock(m_mutex);

	if (isFinished) {
		throw StreamException("ByteArrayBuffer Error:Buffer Finished,Write Failed!");
	}

	if (isClosed) {
		throw StreamException("ByteArrayBuffer Error:Buffer Closed,Write Failed!");
	}

	this->buffer.insert(this->buffer.end(), buffer, buffer + len);
	m_con.notify_all();
}
